package com.lvkerry.orderfood.service.impl;

import com.google.common.collect.ArrayListMultimap;
import com.lvkerry.orderfood.api.ApiBean;
import com.lvkerry.orderfood.entity.MenuEntity;
import com.lvkerry.orderfood.entity.OrderEntity;
import com.lvkerry.orderfood.entity.UserEntity;
import com.lvkerry.orderfood.repository.MenuRepository;
import com.lvkerry.orderfood.repository.OrderRepository;
import com.lvkerry.orderfood.repository.UserDeskRepository;
import com.lvkerry.orderfood.repository.UserRepository;
import com.lvkerry.orderfood.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.util.*;

import static com.lvkerry.orderfood.global.ConstCodeKt.*;
import static com.lvkerry.orderfood.util.StringOpsKt.generateOrderNumber;
import static com.lvkerry.orderfood.util.StringOpsKt.getToday;


/**
 * @author Kerry
 */

@Service
public class OrderServiceImpl implements OrderService {


    private final OrderRepository orderRepository;
    private final UserRepository userRepository;
    private final UserDeskRepository userDeskRepository;
    private final MenuRepository menuRepository;


    @Autowired
    public OrderServiceImpl(OrderRepository orderRepository, UserRepository userRepository, UserDeskRepository userDeskRepository, MenuRepository menuRepository) {
        this.orderRepository = orderRepository;
        this.userRepository = userRepository;
        this.userDeskRepository = userDeskRepository;
        this.menuRepository = menuRepository;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiBean order(Long menuId, int orderStatus, String remark) {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        for (GrantedAuthority authority : authorities) {
            if (!"ROLE_USER".equals(authority.getAuthority())) {
                return new ApiBean.Builder().setStatus(API_ORDER_DENY).setMessage("当前用户的权限不允许下单...").build();
            }
        }


        String orderNo = generateOrderNumber(authentication.getName());

        UserEntity byUsername = userRepository.findByUsername(authentication.getName());
        OrderEntity byOrderNo = orderRepository.findByOrderNo(orderNo);

        int tableNo = byUsername.getUserDeskEntity() == null ? 0 : byUsername.getUserDeskEntity().getTableNo();

        MenuEntity menuEntity = menuRepository.findOne(menuId);

        if (byOrderNo == null) {
            byOrderNo = new OrderEntity();

            byOrderNo.setLunchDate(getToday(LocalDate.now()));
            byOrderNo.setOrderTime(System.currentTimeMillis());
            byOrderNo.setTableNo(tableNo);
            byOrderNo.setRemark(StringUtils.isEmpty(remark) ? null : remark);
            byOrderNo.setOrderNo(orderNo);
            byOrderNo.setOrderStatus(orderStatus);

            byOrderNo.setUserId(byUsername.getUserId());
            byOrderNo.setUsername(byUsername.getUsername());
            byOrderNo.setName(byUsername.getName());

            byOrderNo.setMenuId(menuEntity.getMenuId());
            byOrderNo.setMenuName(menuEntity.getName());
            byOrderNo.setMenuAvatarUrl(menuEntity.getAvatarUrl());
            byOrderNo.setPrice(menuEntity.getPrice());


            OrderEntity save = orderRepository.save(byOrderNo);
            return new ApiBean.Builder().setStatus(API_SUCCESS).setMessage("下单成功").build();
        } else {
            byOrderNo.setOrderTime(System.currentTimeMillis());
            byOrderNo.setOrderStatus(orderStatus);
            byOrderNo.setMenuId(menuEntity.getMenuId());
            byOrderNo.setMenuName(menuEntity.getName());
            byOrderNo.setMenuAvatarUrl(menuEntity.getAvatarUrl());
            byOrderNo.setPrice(menuEntity.getPrice());
            byOrderNo.setRemark(StringUtils.isEmpty(remark) ? null : remark);
            OrderEntity save = orderRepository.save(byOrderNo);
            return new ApiBean.Builder().setStatus(API_SUCCESS).setMessage("订单已更新成功....").build();
        }
    }

    @Override
    public ApiBean updateOrder(String orderNo, Long menuId, String remark) {
        OrderEntity byOrderNo = orderRepository.findByOrderNo(orderNo);
        if (byOrderNo != null) {
            MenuEntity newMenu = menuRepository.findOne(menuId);

            byOrderNo.setRemark(StringUtils.isEmpty(remark) ? null : remark);

            byOrderNo.setMenuId(newMenu.getMenuId());
            byOrderNo.setMenuName(newMenu.getName());
            byOrderNo.setMenuAvatarUrl(newMenu.getAvatarUrl());
            byOrderNo.setPrice(newMenu.getPrice());

            orderRepository.save(byOrderNo);
            return new ApiBean.Builder().setStatus(API_SUCCESS).setMessage("更新成功").build();
        }
        throw new NullPointerException("orderNo = [" + orderNo + "] not found!!");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiBean cancelUserOrder() {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        UserEntity byUsername = userRepository.findByUsername(authentication.getName());

        OrderEntity byUserIdAndAndLunchDate = orderRepository.findByUserIdAndAndLunchDate(byUsername.getUserId(), getToday(LocalDate.now()));

        if (byUserIdAndAndLunchDate == null) {
            return new ApiBean.Builder().setStatus(ORDER_NOT_EXITS).setMessage("今天你还没下单过..").build();
        }
        byUserIdAndAndLunchDate.setOrderStatus(ORDER_USER_CANCLE);
        OrderEntity save = orderRepository.save(byUserIdAndAndLunchDate);
        return new ApiBean.Builder().setStatus(ORDER_EXITS).setMessage("取消成功").build();
    }

    @Override
    public ApiBean getOneDayAllOrders(String lunchDate) {

        List<OrderEntity> allTodayOrder = orderRepository.findByLunchDate(lunchDate);

        ArrayListMultimap<Integer, OrderEntity> dataMap = ArrayListMultimap.create();

        for (OrderEntity entity : allTodayOrder) {
            dataMap.put(entity.getTableNo(), entity);
        }
        List<Map<String, Object>> listData = new ArrayList<>();

        for (Integer key : dataMap.keySet()) {
            List<OrderEntity> todayNativeEntities = dataMap.get(key);
            Map<String, Object> map = new HashMap<>();
            map.put("tableNo", key);
            map.put("items", todayNativeEntities);
            listData.add(map);
        }

        return new ApiBean.Builder().setStatus(API_SUCCESS).setData(listData).build();

    }

    @Override
    public ApiBean getUserHistoryOrder(long timeStamp, int page, int pageCount) {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        UserEntity byUsername = userRepository.findByUsername(authentication.getName());

        Pageable pageable = new PageRequest(page, pageCount, new Sort(Sort.Direction.DESC, "orderTime"));

        Page<OrderEntity> historyOrder = orderRepository.findByUserIdAndOrderTimeIsGreaterThanEqual(byUsername.getUserId(), timeStamp, pageable);

        Map<String, Object> map = new HashMap<>(6);
        map.put("totalPages", historyOrder.getTotalPages());
        map.put("totalElements", historyOrder.getTotalElements());
        map.put("first", historyOrder.isFirst());
        map.put("content", historyOrder.getContent());
        return new ApiBean.Builder().setStatus(API_SUCCESS).setData(map).build();
    }

    @Override
    public ApiBean checkUserTodayOrder() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        for (GrantedAuthority authority : authorities) {
            if (!"ROLE_USER".equals(authority.getAuthority())) {
                return new ApiBean.Builder().setStatus(API_ORDER_DENY).setMessage("当前用户的权限不允许下单...").build();
            }
        }

        UserEntity byUsername = userRepository.findByUsername(authentication.getName());
        OrderEntity isExits = orderRepository.findByUserIdAndAndLunchDate(byUsername.getUserId(), getToday(LocalDate.now()));

        if (isExits != null) {
            return new ApiBean.Builder().setStatus(ORDER_EXITS).setData(isExits).build();
        }
        return new ApiBean.Builder().setStatus(ORDER_NOT_EXITS).build();
    }

    @Override
    public ApiBean getMenuDetailAndUserODesk(Long menuId) {
        MenuEntity one = menuRepository.findOne(menuId);


        return null;
    }
}
